package org.onionframework.persistence.dao.projection;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.criterion.CriteriaQuery;
import org.hibernate.criterion.PropertyProjection;
import org.hibernate.dialect.function.SQLFunctionRegistry;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
import org.onionframework.core.Onion;
import org.onionframework.persistence.query.DatePart;

public class HibernateDatePartProjection extends PropertyProjection {

	private static final long serialVersionUID = 8407858562467963528L;
	
	private static SessionFactoryImplementor factory = Onion.getBean(SessionFactoryImpl.class);
	
	private static SQLFunctionRegistry functions = Onion.getBean(SessionFactoryImpl.class).getSqlFunctionRegistry();
	
	private DatePart part;
	
	public HibernateDatePartProjection(String prop, boolean grouped, DatePart part) {
		super(prop, grouped);
		this.part = part;
	}
	
	public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) 
		throws HibernateException {
		return new Type[] { StandardBasicTypes.INTEGER };
	}
	
	public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) 
	throws HibernateException {
		StringBuffer buf = new StringBuffer();
		String[] cols = criteriaQuery.getColumns( super.getPropertyName(), criteria );
		List<String> args;
		String column;
		args = new ArrayList<String>(1);
		args.add(cols[0]);
		column = functions.findSQLFunction(this.part.name()).render(StandardBasicTypes.INTEGER, args, factory);
		buf.append( column )
			.append(" as y")
			.append(position + 0)
			.append('_');
			
		return buf.toString();
	}
	
	public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) 
	throws HibernateException {
		if (!super.isGrouped()) {
			return super.toGroupSqlString(criteria, criteriaQuery);
		}
		else {
			StringBuffer buf = new StringBuffer();
			String[] cols = criteriaQuery.getColumns( super.getPropertyName(), criteria );
			List<String> args;
			String column;
			args = new ArrayList<String>(1);
			args.add(cols[0]);
			column = functions.findSQLFunction(this.part.name()).render(StandardBasicTypes.INTEGER, args, factory);
			buf.append( column );
			
			return 	buf.toString();
		}
	}

}
